package com.mostka.ws.server;

import java.io.IOException;
import java.util.HashMap;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.websocket.WebSocket;



@SuppressWarnings("serial")
public abstract class WebSocketServlet extends org.eclipse.jetty.websocket.WebSocketServlet implements TextMessageHandler {

	private final HashMap<Integer, Socket> sockets = new HashMap<Integer, Socket>();
	
	protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
		getServletContext().getNamedDispatcher("default").forward(request,response);
	}

	public WebSocket doWebSocketConnect(HttpServletRequest request,String protocol) {
		return new Socket(this,request.getPathInfo().substring(1));
	}
	
	public void send(int token, String message) throws IOException, InvalidTokenException{
		Socket socket = sockets.get(token);
		if (socket==null){
			throw new InvalidTokenException();
		}
		sockets.get(token).sendMessage(message);
	}
	
	public boolean isOpened(int token) throws InvalidTokenException{
		Socket socket = sockets.get(token);
		if (socket==null){
			throw new InvalidTokenException();
		}
		return sockets.get(token).isOpen();
	}

	public class InvalidTokenException extends Exception{};
	
	class Socket implements WebSocket.OnTextMessage {
		private Connection _connection;
		private TextMessageHandler handler;
		private String channel;
		
		public Socket(TextMessageHandler handler, String channel) {
			this.handler=handler;
			this.channel=channel;
		}
		
		@Override
		public void onClose(int closeCode, String message) {
			sockets.remove(this._connection.hashCode());
			handler.onClose(_connection.hashCode(), channel);
		}
		
		@Override
		public void onMessage(String data) {
			handler.onMessage(_connection.hashCode(), channel, data);
		}
		
		public void sendMessage(String data) throws IOException {
			_connection.sendMessage(data);
		}
		
		public boolean isOpen() {
			return _connection.isOpen();
		}
		
		@Override
		public void onOpen(Connection connection) {
			sockets.put(connection.hashCode(), this);
			_connection = connection;
			handler.onJoin(connection.hashCode(), channel);
		}
	}
}
